﻿namespace BM.Tools.WebControls.MForm.Controls.Modifiers
{
    using System;
    using System.ComponentModel;
    using System.Linq;
    using System.Web.UI;

    using BM.Tools.WebControls.MForm.Controls.Additions;
    using BM.Tools.WebControls.MForm.Controls.Items;
    using BM.Tools.WebControls.MForm.Controls.Modifiers.Additions;
    using BM.Tools.WebControls.MForm.Controls.Tabs;
    using BM.Tools.WebControls.MForm.Navigation;

    /// <summary>
    /// A class that adds Tab container and tabs for the items it is bound to.
    /// </summary>
    public class TabbedDisplayModifier : OffspringsOwnerModifier
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="TabbedDisplayModifier"/> class.
        /// </summary>
        public TabbedDisplayModifier()
        {
            ContainerId = "default";
        }

        /// <summary>
        /// Gets or sets ContainerId in order to differentiate tab containers.
        /// </summary>
        /// <value>
        /// The container id.
        /// </value>
        [DefaultValue("default")]
        public string ContainerId
        {
            get;
            set;
        }

        /// <summary>
        /// Gets or sets the selected tab index.
        /// </summary>        
        public int SelectedTabIndex
        {
            get;
            set;
        }

        /// <summary>
        /// Ensures a tab container is created on init to be sure that the viewstate loads fine.
        /// </summary>
        /// <param name="offspring">
        /// The offspring.
        /// </param>
        /// <param name="e">
        /// The event args.
        /// </param>
        protected override void OnBasisInit(OffspringsOwner offspring, EventArgs e)
        {
            CreateOrGetContainer(offspring);
        }

        /// <summary>
        /// Ensures a tab container is created on pre render, becuase it could get lost during offspring recreation during databinding.
        /// </summary>
        /// <param name="offspring">
        /// The offspring.
        /// </param>
        /// <param name="e">
        /// The event args.
        /// </param>
        protected override void OnBasisPreRender(OffspringsOwner offspring, EventArgs e)
        {
            CreateOrGetContainer(offspring);
        }

        /// <summary>
        /// hides the item's title and creates a tab for the item.
        /// </summary>
        /// <param name="offspringItem">
        /// The offspring item.
        /// </param>
        /// <param name="e">
        /// The event args.
        /// </param>
        protected override void OnItemPreRender(OffspringsOwnerItem offspringItem, EventArgs e)
        {
            offspringItem.Additions.Add(CreateAddition());
            offspringItem.Title.Visible = false;

            if (offspringItem.IsPrototypeDescendant())
            {
                return;
            }

            AddTab(offspringItem);
        }

        private static FormTabContainer CreateOrGetContainer(OffspringsOwner offspring, string containerId)
        {
            OffspringsOwnerItem parent = offspring.ParentItem;
            FormTabContainer container;
            foreach (Control sibling in parent.Controls)
            {
                container = GetTabContainer(sibling, containerId);
                if (container != null)
                {
                    return container;
                }
            }

            container = new FormTabContainer
            {
                ID = containerId
            };
            offspring.Controls.AddAt(0, container);
            return container;
        }

        /// <summary>
        /// gets the tab container
        /// </summary>
        /// <param name="sibling">
        /// The sibling.
        /// </param>
        /// <param name="containerId">
        /// The container Id.
        /// </param>
        /// <returns>
        /// the tab container
        /// </returns>
        private static FormTabContainer GetTabContainer(Control sibling, string containerId)
        {
            if (!(sibling is OffspringsOwner))
            {
                return null;
            }

            if (!sibling.HasControls())
            {
                return null;
            }

            foreach (Control c in sibling.Controls)
            {
                var container = c as FormTabContainer;

                if (container != null && container.ID == containerId)
                {
                    return container;
                }
            }

            return null;
        }

        private void AddTab(OffspringsOwnerItem offspringItem)
        {
            FormTabContainer container = CreateOrGetContainer(offspringItem.Basis);
            if (!offspringItem.IsPrototypeItem)
            {
                if (!container.Tabs.Any(tab => tab.TargetControl.ClientID == offspringItem.ClientID))
                {
                    container.Tabs.Add(new FormTab(offspringItem));
                }
            }

            container.SelectedTabIndex = SelectedTabIndex;
        }

        /// <summary>
        /// creates a TabbedDisplayAddition for the item
        /// </summary>
        /// <returns>
        /// the tabbed display addition
        /// </returns>
        private Addition CreateAddition()
        {
            return new TabbedDisplayAddition(this);
        }        

        /// <summary>
        /// creates or gets tab container
        /// </summary>
        /// <param name="offspring">
        /// The offspring.
        /// </param>
        /// <returns>
        /// the tab container
        /// </returns>
        private FormTabContainer CreateOrGetContainer(OffspringsOwner offspring)
        {
            return CreateOrGetContainer(offspring, ContainerId);
        }
    }
}